using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using AutomaticSubtitles.Service.DataAccess;
using AutomaticSubtitles.Service.DataAccess.Model;
using AutomaticSubtitles.Service.Domain.Filter;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.DependencyInjection;

namespace AutomaticSubtitles.Service.Infrastructure.Helper;

/// <summary>
/// 词语过滤辅助类
/// </summary>
public class WordFilterHelper
{
    private static readonly SemaphoreSlim _cacheLock = new(1, 1);
    private static readonly ILogger _logger = LoggingHelper.GetLogger(typeof(WordFilterHelper).FullName);

    // 缓存通用过滤词
    private static List<string> _commonFilterWords = new();
    // 缓存特定语言过滤词，键为语言代码
    private static readonly Dictionary<string, List<string>> _languageFilterWords = new();
    // 缓存上次更新时间
    private static DateTime _lastUpdateTime = DateTime.MinValue;
    // 缓存过期时间（15分钟）
    private static readonly TimeSpan _cacheExpirationTime = TimeSpan.FromMinutes(15);
    // 是否已完成初始化
    private static bool _isInitialized = false;
    // 已初始化的语言集合
    private static HashSet<string> _initializedLanguages = new();
    // 默认语言列表，当无法从数据库获取时使用
    private static readonly List<string> _defaultLanguages = new() { "en", "zh", "ja", "fr", "es", "de", "ko", "ru" };

    /// <summary>
    /// 显式初始化过滤词缓存，建议在应用启动时调用
    /// </summary>
    /// <param name="repository">过滤词仓储</param>
    /// <returns>初始化任务</returns>
    public static async Task InitializeAsync(IFilterWordsRepository repository)
    {
        if (_isInitialized && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
        {
            _logger.LogInformation("过滤词缓存已初始化且未过期，跳过初始化");
            return;
        }

        _logger.LogInformation("开始显式初始化过滤词缓存...");
        await ForceUpdateFilterWordsAsync(repository);
        _isInitialized = true;
        _logger.LogInformation("过滤词缓存初始化完成");
    }

    /// <summary>
    /// 为特定语言初始化过滤词缓存，适合在处理第一个片段时调用
    /// </summary>
    /// <param name="language">语言代码</param>
    /// <param name="repository">过滤词仓储</param>
    /// <returns>初始化任务</returns>
    public static async Task InitializeForLanguageAsync(string language, IFilterWordsRepository repository)
    {
        if (string.IsNullOrWhiteSpace(language))
        {
            throw new ArgumentException("语言代码不能为空", nameof(language));
        }

        // 如果全局缓存已初始化且未过期，直接返回
        if (_isInitialized && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
        {
            _logger.LogInformation($"过滤词缓存已全局初始化且未过期，跳过语言 '{language}' 的单独初始化");
            return;
        }

        // 如果特定语言已初始化且缓存未过期，直接返回
        if (_initializedLanguages.Contains(language) && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
        {
            _logger.LogInformation($"语言 '{language}' 的过滤词缓存已初始化且未过期，跳过初始化");
            return;
        }

        await _cacheLock.WaitAsync();
        try
        {
            // 再次检查
            if (_initializedLanguages.Contains(language) && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
            {
                return;
            }

            _logger.LogInformation($"开始为语言 '{language}' 初始化过滤词缓存...");

            // 确保通用过滤词已加载
            if (_commonFilterWords.Count == 0 || DateTime.Now - _lastUpdateTime >= _cacheExpirationTime)
            {
                _commonFilterWords = await repository.GetActiveFilterWordsAsync();
                _logger.LogInformation($"已加载 {_commonFilterWords.Count} 个通用过滤词");
            }

            // 加载特定语言的过滤词
            var words = await repository.GetActiveLanguageFilterWordsAsync(language);
            if (words.Count > 0)
            {
                _languageFilterWords[language] = words;
                _logger.LogInformation($"为语言 '{language}' 加载了 {words.Count} 个过滤词");
            }
            else
            {
                _logger.LogWarning($"未找到语言 '{language}' 的过滤词");
                // 确保语言键存在，即使没有过滤词
                if (!_languageFilterWords.ContainsKey(language))
                {
                    _languageFilterWords[language] = new List<string>();
                }
            }

            // 更新缓存时间和初始化状态
            if (DateTime.Now - _lastUpdateTime >= _cacheExpirationTime)
            {
                _lastUpdateTime = DateTime.Now;
            }

            _initializedLanguages.Add(language);
            _logger.LogInformation($"语言 '{language}' 的过滤词缓存初始化完成");
        }
        finally
        {
            _cacheLock.Release();
        }
    }

    /// <summary>
    /// 检查文本是否包含需要过滤的词语
    /// </summary>
    /// <param name="text">要检查的文本</param>
    /// <param name="language">语言代码</param>
    /// <param name="repository">过滤词仓储</param>
    /// <param name="isFirstSegment">是否为第一个文本片段，如果是将预加载语言相关过滤词</param>
    /// <returns>如果包含需要过滤的词语则返回true，否则返回false</returns>
    public static async Task<bool> ShouldFilterTextAsync(string text, string language, IFilterWordsRepository repository, bool isFirstSegment = false)
    {
        if (string.IsNullOrWhiteSpace(text)) return false;

        // 如果是第一个片段且指定了语言，预加载该语言的过滤词
        if (isFirstSegment && !string.IsNullOrWhiteSpace(language))
        {
            await InitializeForLanguageAsync(language, repository);
        }
        // 否则，如果尚未初始化或缓存已过期，则更新缓存
        else if (!_isInitialized || DateTime.Now - _lastUpdateTime >= _cacheExpirationTime)
        {
            await UpdateFilterWordsIfNeededAsync(repository);
        }

        // 检查通用过滤词
        foreach (var word in _commonFilterWords)
        {
            if (ContainsWord(text, word))
            {
                _logger.LogInformation($"文本 '{text}' 包含通用过滤词 '{word}'，将被过滤");
                return true;
            }
        }

        // 检查特定语言过滤词
        if (!string.IsNullOrWhiteSpace(language) && _languageFilterWords.TryGetValue(language, out var languageWords))
        {
            foreach (var word in languageWords)
            {
                if (ContainsWord(text, word))
                {
                    _logger.LogInformation($"文本 '{text}' 包含语言 '{language}' 特定过滤词 '{word}'，将被过滤");
                    return true;
                }
            }
        }

        return false;
    }

    /// <summary>
    /// 如果需要，更新过滤词缓存
    /// </summary>
    /// <param name="repository">过滤词仓储</param>
    private static async Task UpdateFilterWordsIfNeededAsync(IFilterWordsRepository repository)
    {
        // 检查缓存是否过期
        if (_isInitialized && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
            return;

        await ForceUpdateFilterWordsAsync(repository);
    }

    /// <summary>
    /// 强制更新过滤词缓存，无视缓存状态
    /// </summary>
    /// <param name="repository">过滤词仓储</param>
    private static async Task ForceUpdateFilterWordsAsync(IFilterWordsRepository repository)
    {
        await _cacheLock.WaitAsync();
        try
        {
            // 再次检查，防止其他线程已经更新
            if (_isInitialized && DateTime.Now - _lastUpdateTime < _cacheExpirationTime)
                return;

            _logger.LogInformation("开始更新过滤词缓存...");

            // 更新通用过滤词
            _commonFilterWords = await repository.GetActiveFilterWordsAsync();

            // 清空并更新所有语言的过滤词
            _languageFilterWords.Clear();
            _initializedLanguages.Clear();

            try
            {
                // 从仓储获取所有活跃的语言
                var languages = await repository.GetActiveLanguagesAsync();

                _logger.LogInformation($"从仓储中获取到 {languages.Count} 种语言的过滤词配置");

                // 如果没有找到任何语言，使用常见语言列表作为备用
                if (languages.Count == 0)
                {
                    languages = _defaultLanguages;
                    _logger.LogWarning("仓储中未找到任何语言过滤词配置，使用默认语言列表");
                }

                foreach (var lang in languages)
                {
                    var words = await repository.GetActiveLanguageFilterWordsAsync(lang);
                    if (words.Count > 0)
                    {
                        _languageFilterWords[lang] = words;
                        _initializedLanguages.Add(lang);
                        _logger.LogInformation($"为语言 '{lang}' 加载了 {words.Count} 个过滤词");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取语言过滤词时出错，使用默认语言列表");

                // 出错时使用默认语言列表
                foreach (var lang in _defaultLanguages)
                {
                    try
                    {
                        var words = await repository.GetActiveLanguageFilterWordsAsync(lang);
                        if (words.Count > 0)
                        {
                            _languageFilterWords[lang] = words;
                            _initializedLanguages.Add(lang);
                        }
                    }
                    catch (Exception innerEx)
                    {
                        _logger.LogError(innerEx, $"获取语言 '{lang}' 的过滤词时出错");
                    }
                }
            }

            _lastUpdateTime = DateTime.Now;
            _isInitialized = true;
            _logger.LogInformation($"过滤词缓存已更新。通用词 {_commonFilterWords.Count} 个，语言特定词 {_languageFilterWords.Count} 种语言");
        }
        finally
        {
            _cacheLock.Release();
        }
    }

    /// <summary>
    /// 检查文本是否包含指定词语（忽略大小写）
    /// </summary>
    private static bool ContainsWord(string text, string word)
    {
        if (string.IsNullOrWhiteSpace(word)) return false;

        try
        {
            // 使用正则表达式匹配完整词语（边界匹配）
            return Regex.IsMatch(text, $@"\b{Regex.Escape(word)}\b", RegexOptions.IgnoreCase);
        }
        catch (Exception ex)
        {
            // 正则表达式可能会因为特殊字符而失败，使用简单的包含检查作为备用
            _logger.LogWarning(ex, $"对过滤词 '{word}' 执行正则匹配失败，改用简单包含匹配");
            return text.IndexOf(word, StringComparison.OrdinalIgnoreCase) >= 0;
        }
    }

    /// <summary>
    /// 简化版本的过滤检查方法，不需要传递仓储实例
    /// </summary>
    /// <param name="text">要检查的文本</param>
    /// <param name="language">语言代码</param>
    /// <returns>如果包含需要过滤的词语则返回true，否则返回false</returns>
    public static async Task<bool> ShouldFilterTextSimpleAsync(string text, string language)
    {
        if (string.IsNullOrWhiteSpace(text)) return false;

        // 检查缓存是否过期
        if (!_isInitialized || DateTime.Now - _lastUpdateTime >= _cacheExpirationTime)
        {
            try
            {
                // 尝试获取所有启用的过滤词
                try
                {
                    // 先尝试直接解析 - 适用于单例服务
                    var repository = DependencyResolver.Resolve<IFilterWordsRepository>();
                    if (repository != null)
                    {
                        await UpdateFilterWordsIfNeededAsync(repository);
                    }
                }
                catch (InvalidOperationException ex) when (ex.Message.Contains("scoped"))
                {
                    _logger.LogInformation("尝试使用作用域解析过滤词仓储");
                    // 如果是作用域服务解析错误，尝试创建作用域
                    try
                    {
                        using (var scope = DependencyResolver.ServiceProvider.CreateScope())
                        {
                            var repository = scope.ServiceProvider.GetService<IFilterWordsRepository>();
                            if (repository != null)
                            {
                                await UpdateFilterWordsIfNeededAsync(repository);
                            }
                            else
                            {
                                _logger.LogWarning("无法通过作用域获取过滤词仓储实例");
                            }
                        }
                    }
                    catch (Exception scopeEx)
                    {
                        _logger.LogWarning($"通过作用域获取过滤词仓储时出错: {scopeEx.Message}");
                    }
                }
                catch (Exception otherEx)
                {
                    _logger.LogWarning($"获取过滤词仓储时出现未预期的错误: {otherEx.Message}");
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "获取过滤词仓储实例时出错，将使用现有缓存（如果有）");
            }
        }

        // 检查通用过滤词
        foreach (var word in _commonFilterWords)
        {
            if (ContainsWord(text, word))
            {
                _logger.LogInformation($"文本 '{text}' 包含通用过滤词 '{word}'，将被过滤");
                return true;
            }
        }

        // 检查特定语言过滤词
        if (!string.IsNullOrWhiteSpace(language) && _languageFilterWords.TryGetValue(language, out var languageWords))
        {
            foreach (var word in languageWords)
            {
                if (ContainsWord(text, word))
                {
                    _logger.LogInformation($"文本 '{text}' 包含语言 '{language}' 特定过滤词 '{word}'，将被过滤");
                    return true;
                }
            }
        }

        return false;
    }
}